﻿#region
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Reflection;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;

#endregion


namespace hf_plat_core
{
	/// <summary>
	/// 	时间类型
	/// </summary>
	public enum EnumIntervalType
	{
		/// <summary>
		/// 秒
		/// </summary>
		Sec,

		/// <summary>
		/// 	分
		/// </summary>
		Min,

		/// <summary>
		/// 	时
		/// </summary>
		Hour,

		/// <summary>
		/// 	日
		/// </summary>
		Day,

		/// <summary>
		/// 	周
		/// </summary>
		Week,

		/// <summary>
		/// 	月
		/// </summary>
		Month,

		/// <summary>
		/// 	年
		/// </summary>
		Year,
	}

	/// <summary>
	/// 
	/// </summary>
	public class DataSeries : Collection<double>
	{
		internal string SeriesName
		{
			get { return _name; }
		}

		/// <summary>
		/// 	指标中的DataSeries在被取值时this[n]运算指标
		/// </summary>
		internal Indicator Idc = null;

		private readonly string _name;

		/// <summary>
		/// 构建函数(参数勿填)
		/// </summary>
		/// <param name="pSeriesName"></param>
		public DataSeries([CallerMemberName] string pSeriesName = null)
		{
			//根据变量名，赋值member
			//this.SeriesName = new StackTrace(true).GetFrame(1).GetMethod().Name; // pSeriesName; .Net4下结果不正确(.cto)
			_name = pSeriesName;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="index"></param>
		/// <returns></returns>
		public new double this[int index]
		{
			get
			{
				double rtn = double.NaN;
				if (this.Idc != null)// && !this.idc.IsOperated)
				{
					//在策略调用时处理:此处会导致循环调用
					//this.idc.isUpdated = false;
					this.Idc.update();// .OnBarUpdate();
				}
				if (Count - 1 - index >= 0)
				{
					rtn = base[Count - 1 - index];
				}
				return rtn;
			}
			set
			{
				if (Count - 1 - index < 0)
				{
					return;
				}
				base[Count - 1 - index] = value;
			}
		}
	}


	/// <summary>
	/// 自定义集合变化事件
	/// </summary>
	/// <param name="pType"></param>
	/// <param name="pNew"></param>
	/// <param name="pOld"></param>
	public delegate void CollectionChange(int pType, object pNew, object pOld);

	/// <summary>
	/// 	数据集合
	/// </summary>
	public class DataCollection : Collection<Data>
	{
		private CollectionChange _onChange;
		/// <summary>
		/// 数据变化:加1;减-1;更新0
		/// </summary>
		public event CollectionChange OnChanged
		{
			add
			{
				_onChange += value;
			}
			remove
			{
				_onChange -= value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="index"></param>
		/// <param name="item"></param>
		protected override void InsertItem(int index, Data item)
		{
			base.InsertItem(index, item);
			if (_onChange != null)
			{
				_onChange(1, item, null);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="index"></param>
		/// <param name="item"></param>
		protected override void SetItem(int index, Data item)
		{
			Data old = this[index];
			base.SetItem(index, item);
			if (_onChange != null)
			{
				_onChange(0, item, old);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="index"></param>
		protected override void RemoveItem(int index)
		{
			Data old = this[index];
			base.RemoveItem(index);
			if (_onChange != null)
			{
				_onChange(-1, old, old);
			}
		}
	}

	/// <summary>
	/// </summary>
	public class StrategyCollection : Collection<Strategy>
	{
		private CollectionChange _onChange;
		/// <summary>
		/// 策略变化:加1;减-1;更新0
		/// </summary>
		public event CollectionChange OnChanged
		{
			add
			{
				_onChange += value;
			}
			remove
			{
				_onChange -= value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="index"></param>
		/// <param name="item"></param>
		protected override void InsertItem(int index, Strategy item)
		{
			base.InsertItem(index, item);
			if (_onChange != null)
			{
				_onChange(1, item, null);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="index"></param>
		/// <param name="item"></param>
		protected override void SetItem(int index, Strategy item)
		{
			Strategy old = this[index];
			base.SetItem(index, item);
			if (_onChange != null)
			{
				_onChange(0, item, old);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="index"></param>
		protected override void RemoveItem(int index)
		{
			Strategy old = this[index];
			base.RemoveItem(index);
			if (_onChange != null)
			{
				_onChange(-1, old, old);
			}
		}
	}

	#region 自定义属性:类中需继承CustomTypeDescriptor,如需直接改写属性,重新定义继承CustomPropertyDescriptor的类并重写Setvalue
	/// <summary>
	/// </summary>
	public class CustomTypeDescriptor : ICustomTypeDescriptor
	{
		internal ConcurrentDictionary<string, Property> DicProperties = new ConcurrentDictionary<string, Property>();

		internal void Add(Property value)
		{
			if (value != null)
			{
				this.DicProperties.TryAdd(value.Name, value);
			}
		}

		#region ICustomTypeDescriptor 成员
		PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
		{
			PropertyDescriptor[] newProps = new PropertyDescriptor[this.DicProperties.Count];
			//for (int i = 0; i < this.dicProperties.Count; i++)
			int i = 0;
			foreach (var v in this.DicProperties)
			{
				//Property prop = (Property)this[i];
				Property prop = v.Value;
				newProps[i++] = new CustomPropertyDescriptor(ref prop, attributes);
			}
			return new PropertyDescriptorCollection(newProps);
		}

		AttributeCollection ICustomTypeDescriptor.GetAttributes()
		{
			return TypeDescriptor.GetAttributes(this, true);
		}

		string ICustomTypeDescriptor.GetClassName()
		{
			return TypeDescriptor.GetClassName(this, true);
		}

		string ICustomTypeDescriptor.GetComponentName()
		{
			return TypeDescriptor.GetComponentName(this, true);
		}

		TypeConverter ICustomTypeDescriptor.GetConverter()
		{
			return TypeDescriptor.GetConverter(this, true);
		}

		EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
		{
			return TypeDescriptor.GetDefaultEvent(this, true);
		}

		PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
		{
			return TypeDescriptor.GetDefaultProperty(this, true);
		}

		object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
		{
			return TypeDescriptor.GetEditor(this, editorBaseType, true);
		}

		EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
		{
			return TypeDescriptor.GetEvents(this, attributes, true);
		}

		EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
		{
			return TypeDescriptor.GetEvents(this, true);
		}

		PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
		{
			return TypeDescriptor.GetProperties(this, true);
		}

		object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
		{
			return this;
		}
		#endregion

		/*
		private void Remove(Property value)
		{
			Property t;
			DicProperties.TryRemove(value.Name, out t);
		}
*/
	}

	/// <summary>
	/// 	自定义属性类
	/// </summary>
	internal class Property
	{
		private string _category = string.Empty;
		private string _displayname = string.Empty;
		private string _name = string.Empty;
		private bool _visible = true;

		public Property(string sName, object sValue)
		{
			this._name = sName;
			this.Value = sValue;
		}

		public Property(string sName, object sValue, bool sReadonly, bool sVisible)
		{
			this._name = sName;
			this.Value = sValue;
			this.ReadOnly = sReadonly;
			this._visible = sVisible;
		}

		public string Name //获得属性名   
		{
			get { return this._name; }
			set { this._name = value; }
		}

		public string Description //属性显示名称   
		{
			get { return this._displayname; }
			set { this._displayname = value; }
		}

		public TypeConverter Converter //类型转换器，我们在制作下拉列表时需要用到   
		{ get; set; }

		public string Category //属性所属类别   
		{
			get { return this._category; }
			set { this._category = value; }
		}

		public object Value //属性值   
		{ get; set; }

		public bool ReadOnly //是否为只读属性   
		{ get; set; }

		public bool Visible //是否可见   
		{
			get { return this._visible; }
			set { this._visible = value; }
		}

		public virtual object Editor //属性编辑器   
		{ get; set; }
	}

	/// <summary>
	/// 	自定义属性描述
	/// </summary>
	internal class CustomPropertyDescriptor : PropertyDescriptor
	{
		protected Property Property;

		public CustomPropertyDescriptor(ref Property myProperty, Attribute[] attrs)
			: base(myProperty.Name, attrs)
		{
			this.Property = myProperty;
		}

		#region PropertyDescriptor 重写方法
		public override Type ComponentType { get { return null; } }

		public override string Description
		{
			get
			{
				//return m_Property.Name;
				return this.Property.Description != "" ? this.Property.Description : this.Property.Name;
			}
		}

		public override string Category { get { return this.Property.Category; } }

		public override string DisplayName
		{
			get
			{
				return this.Property.Name;
				//return m_Property.DisplayName != "" ? m_Property.DisplayName : m_Property.Name;
			}
		}

		public override bool IsReadOnly { get { return this.Property.ReadOnly; } }

		public override TypeConverter Converter { get { return this.Property.Converter; } }

		public override Type PropertyType { get { return this.Property.Value.GetType(); } }

		public override bool CanResetValue(object component)
		{
			return false;
		}

		public override object GetValue(object component)
		{
			return this.Property.Value;
		}

		public override void ResetValue(object component)
		{
			//Have to implement   
		}

		public override bool ShouldSerializeValue(object component)
		{
			return false;
		}

		public override void SetValue(object component, object value)
		{
			if (component.GetType().BaseType == typeof(Strategy)) // .FullName == "GFCTP.Strategy")
			{
				FieldInfo fieldInfo = component.GetType().GetField(this.Property.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(component, value);
				}
			}
			this.Property.Value = value;
		}

		public override object GetEditor(Type editorBaseType)
		{
			return this.Property.Editor ?? base.GetEditor(editorBaseType);
		}
		#endregion
	}
	#endregion
}

namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	public class CallerMemberNameAttribute : Attribute { }
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	public class CallerFilePathAttribute : Attribute { }
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	public class CallerLineNumberAttribute : Attribute { }
}